home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #5 / Amiga Plus CD - 2000 - No. 5.iso / Tools / Dev / FPSE_src / system / win32 / rs232.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-01  |  7.4 KB  |  302 lines

  1. /*
  2.     RS232 - Map the serial port of the PSX to a PC COMx
  3.   ================================================================
  4.   This code is done for making an easy conversion to plugin format
  5.   ================================================================
  6. */
  7. #include <windows.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11.  
  12. #include "fpse.h"
  13.  
  14. //#define DEBUG_SERIAL
  15.  
  16. #ifndef DEBUG_SERIAL
  17. #define SERPORT     FPSEIni.ComName
  18. #else
  19. #define SERPORT     DefaultSerialPort
  20. #endif
  21.  
  22. static HANDLE    h;
  23. static HANDLE    hcom;
  24. static int       rs232=0;
  25. static SIO_Type *SioRs232;
  26. static char     *DefaultSerialPort = "COM1";
  27.  
  28. DWORD CALLBACK ComThread( HANDLE h )
  29. {
  30.  DWORD      mask;
  31.  DWORD      read,ret;
  32.  DWORD      dwModemStatus;
  33.  OVERLAPPED osRead = { 0 };
  34.  char       ch;
  35.  
  36. // wait for received characters
  37.  if( !SetCommMask(h,EV_CTS | EV_DSR | EV_RXCHAR) ) {
  38.     printf("SetCommMask failed\n");
  39.     return FPSE_ERR;
  40.  }
  41.  
  42.  while (!rs232) ;
  43.  
  44.  do {
  45. // get the event mask
  46.     if( WaitCommEvent(h, &mask, NULL) ) {
  47. #ifdef DEBUG_SERIAL
  48.         printf("event happen\n");
  49. #endif
  50.         read=0;
  51.         if (mask & EV_RXCHAR) {
  52.             do {
  53.                 ret = ReadFile(h,&ch,1,&read,&osRead);
  54.                 if (!ret && GetLastError() != ERROR_IO_PENDING) break;
  55.             } while (!ret);
  56.             if (!ret) {
  57.                 printf("Error in ReadFile(%s)\n",SERPORT);
  58.                 read = 0;
  59.             }
  60.         }
  61.  
  62.         if ( mask & (EV_CTS|EV_DSR) ) {
  63.             if (!GetCommModemStatus(h, &dwModemStatus)) {
  64.                 printf("Error in GetCommModemStatus\n");
  65.                 break;
  66.             }
  67.             if (mask & EV_CTS) {
  68.                 SioRs232->Delta |= CTS;
  69.                 if (MS_CTS_ON & dwModemStatus) SioRs232->Status |= CTS;
  70.                                           else SioRs232->Status &= ~CTS;
  71.             }
  72.             if (mask & EV_DSR) {
  73.                 SioRs232->Delta |= DSR;
  74.                 if (MS_DSR_ON & dwModemStatus) SioRs232->Status |= DSR;
  75.                                           else SioRs232->Status &= ~DSR;
  76.             }
  77. #ifdef DEBUG_SERIAL
  78.             if (SioRs232->Status & CTS) printf("CTS ON\n");
  79.                                    else printf("CTS OFF\n");
  80.             if (SioRs232->Status & DSR) printf("DSR ON\n");
  81.                                    else printf("DSR OFF\n");
  82. #endif
  83.         }
  84. #ifndef DEBUG_SERIAL
  85.         sio_async(SioRs232,&ch,read);
  86. #endif
  87.         mask = 0;
  88.     }
  89.  } while(rs232);
  90.  
  91. // tell terminal thread to quit
  92.  printf("Shutdown serial emulator.\n");
  93.  SetCommMask(h,0);
  94.  
  95.  return FPSE_OK;
  96. }
  97.  
  98. int RS232_Init(SIO_Type *sio)
  99. {
  100.     DWORD        id;
  101.     COMMTIMEOUTS timeouts;
  102.  
  103. // check if the driver is already installed
  104.     if (rs232) return FPSE_WARN;
  105.  
  106. #ifndef DEBUG_SERIAL
  107.     if (SERPORT == NULL) SERPORT = DefaultSerialPort;
  108. #endif
  109.  
  110. // open port for overlapped I/O
  111.     h = CreateFile(SERPORT,
  112.                    GENERIC_READ|GENERIC_WRITE,
  113.                    0,NULL,
  114.                    OPEN_EXISTING,
  115.                    FILE_FLAG_OVERLAPPED,
  116.                    NULL);
  117.  
  118.     if (h == INVALID_HANDLE_VALUE) return FPSE_ERR;
  119.  
  120. // set time-out
  121.     timeouts.ReadIntervalTimeout         = 0;
  122.     timeouts.ReadTotalTimeoutMultiplier  = 0;
  123.     timeouts.ReadTotalTimeoutConstant    = 0;
  124.     timeouts.WriteTotalTimeoutMultiplier = 0;
  125.     timeouts.WriteTotalTimeoutConstant   = 0;
  126.  
  127.     if (!SetCommTimeouts(h, &timeouts)) {
  128.         printf("Error setting time-outs.\n");
  129.         CloseHandle(h);
  130.         return FPSE_ERR;
  131.     }
  132.  
  133. // Set default rate at 9600, 8bit, 1stop
  134.     sio->Baud = SIOBAUDCLOCK/9600;
  135.     sio->Mode = PRESCALER1 | BYTE8BIT | STOP1BIT;
  136.     sio->IrqSrc = SIO_IRQ_IMM;
  137.  
  138. // Update physical port
  139.     RS232_UpdateStatus(sio);
  140.  
  141. // Create Thread
  142.     SioRs232 = sio;
  143.     hcom = CreateThread(NULL,0,ComThread,h,0,&id);
  144.     if( hcom == INVALID_HANDLE_VALUE ) {
  145.         printf("CreateThread failed\n");
  146.         return FPSE_ERR;
  147.     }
  148.  
  149. // Now the driver is correctly installed
  150.     rs232 = 1;
  151.  
  152.     return FPSE_OK;
  153. }
  154.  
  155. void RS232_Close(SIO_Type *sio)
  156. {
  157.  if (!rs232) return;
  158.  
  159.  TerminateThread(hcom,0);
  160.  CloseHandle(hcom);
  161.  CloseHandle(h);
  162.  rs232 = 0;
  163. }
  164.  
  165. static BOOL WriteABuffer(char * lpBuf, DWORD dwToWrite)
  166. {
  167.    OVERLAPPED osWrite = {0};
  168.    DWORD dwWritten;
  169.    DWORD dwRes;
  170.    BOOL fRes;
  171.  
  172.    // Create this write operation's OVERLAPPED structure's hEvent.
  173.    osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  174.    if (osWrite.hEvent == NULL)
  175.       // error creating overlapped event handle
  176.       return FALSE;
  177.  
  178.    // Issue write.
  179.    if (!WriteFile(h, lpBuf, dwToWrite, &dwWritten, &osWrite)) {
  180.       if (GetLastError() != ERROR_IO_PENDING) { 
  181.          // WriteFile failed, but isn't delayed. Report error and abort.
  182.          fRes = FALSE;
  183.       }
  184.       else {
  185.          // Write is pending.
  186.          dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);
  187.          switch(dwRes)
  188.          {
  189.             // OVERLAPPED structure's event has been signaled. 
  190.             case WAIT_OBJECT_0:
  191.                  if (!GetOverlappedResult(h, &osWrite, &dwWritten, TRUE)) // FALSE))
  192.                        fRes = FALSE;
  193.                  else
  194.                   // Write operation completed successfully.
  195.                   fRes = TRUE;
  196.                  break;
  197.             
  198.             default:
  199.                  // An error has occurred in WaitForSingleObject.
  200.                  // This usually indicates a problem with the
  201.                 // OVERLAPPED structure's event handle.
  202.                  fRes = FALSE;
  203.                  break;
  204.          }
  205.       }
  206.    }
  207.    else
  208.       // WriteFile completed immediately.
  209.       fRes = TRUE;
  210.  
  211.    CloseHandle(osWrite.hEvent);
  212.    return fRes;
  213. }
  214.  
  215. void RS232_WriteData(SIO_Type *sio)
  216. {
  217.     if ( WriteABuffer(sio->TxBuf,sio->TxNum) != TRUE) {
  218.         printf("WriteFile failed\n");
  219.     }
  220. }
  221.  
  222. void RS232_UpdateStatus(SIO_Type *sio)
  223. {
  224.     DCB dcb;
  225.  
  226. // set DCB
  227.     memset(&dcb,0,sizeof(dcb));
  228.     dcb.DCBlength = sizeof(dcb);
  229.  
  230. // Setup baud rate
  231.     switch (sio->Mode & 3) {
  232.     case 0:
  233.     case 1:
  234.         dcb.BaudRate = SIOBAUDCLOCK / sio->Baud;
  235.         break;
  236.     case 2:
  237.         dcb.BaudRate = SIOBAUDCLOCK / (sio->Baud*16);
  238.         break;
  239.     case 3:
  240.         dcb.BaudRate = SIOBAUDCLOCK / (sio->Baud*64);
  241.         break;
  242.     }
  243.  
  244. // Setup parity
  245.     if (sio->Mode & PARITY) {
  246.         if (sio->Mode & PARITY_ODDEVEN) dcb.Parity = ODDPARITY;
  247.                                    else dcb.Parity = EVENPARITY;
  248.     } else dcb.Parity = NOPARITY;
  249.  
  250. // Setup byte lenght
  251.     dcb.ByteSize = 5 + ((sio->Mode >> 2) & 0x3);
  252.  
  253. // Setup stop bit lenght
  254.     switch (sio->Mode & 0xC0) {
  255.     case 0:
  256.     case STOP1BIT:
  257.         dcb.StopBits = ONESTOPBIT;
  258.         break;
  259.     case STOP15BIT:
  260.         dcb.StopBits = ONE5STOPBITS;
  261.         break;
  262.     case STOP2BIT:
  263.         dcb.StopBits = TWOSTOPBITS;
  264.         break;
  265.     }
  266.  
  267.     dcb.fBinary = 1;
  268.     if (sio->Ctrl.Control8.Line & DTR) dcb.fDtrControl = DTR_CONTROL_ENABLE;
  269.                                   else dcb.fDtrControl = DTR_CONTROL_DISABLE;
  270.  
  271.     if (sio->Ctrl.Control8.Line & RTS) dcb.fRtsControl = RTS_CONTROL_ENABLE;
  272.                                   else dcb.fRtsControl = RTS_CONTROL_DISABLE;
  273.  
  274.     dcb.fOutxCtsFlow = FALSE;
  275.     dcb.fOutxDsrFlow = FALSE;
  276.  
  277.     if(!SetCommState(h,&dcb))
  278.         printf("RS232_UpdateStatus() failed\n");
  279. }
  280.  
  281. #ifdef DEBUG_SERIAL
  282. #include <conio.h>
  283. char str[]={"ciao"};
  284. void main()
  285. {
  286.  SIO_Type sio;
  287.  
  288.  sio.FifoSize = 4;
  289.  if (RS232_Init(&sio) != FPSE_OK) {
  290.     printf("non configuro il sio\n");
  291.     return;
  292.  }
  293.  
  294.  memcpy(sio.TxBuf,str,4);
  295.  sio.TxNum = 4;
  296.  RS232_WriteData(&sio);
  297.  while (getch() != 27);
  298.  
  299.  RS232_Close(&sio);
  300. }
  301. #endif
  302.